package com.laviedesfons.jhmtasc.types.internals;

import com.laviedesfons.jhmtasc.exceptions.MException;
import com.laviedesfons.jhmtasc.metadata.MetaType;
import com.laviedesfons.jhmtasc.types.interfaces.GenericType;
import com.laviedesfons.jhmtasc.types.interfaces.InternalType;
import com.laviedesfons.jhmtasc.types.interfaces.ToArray;
import fr.x9c.cadmium.kernel.Block;
import fr.x9c.cadmium.kernel.Value;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * @author Romano
 */
public abstract class PNup implements ToArray, GenericType {

    protected List<InternalType> values;
    protected MetaType[] params;

    @Override
    public void setParams(MetaType... cls) {
        params = cls;
    }

    public PNup(MetaType ... cls) {
        params = cls;
    }

    @Override
    public List<InternalType> values(){
        return values;
    }

    @Override
    public PNup fromValue(Value v) throws MException {
        if (!(v.isBlock() && params !=null && params.length >= 1
                && (params.length == v.asBlock().sizeValues()))) {
            throw new MException("PNup error ...");
        }

        values = new ArrayList<InternalType>();

        if (params.length == 1){
            values.add(params[0].create().fromValue(v));
            return this;
        }

        for (int i = 0; v.isBlock() && i < v.asBlock().sizeValues(); i++) {
            values.add(params[i].create().fromValue(v.asBlock().get(i)));
        }
        return this;
    }

    @Override
    public Value toValue() {
        if (values.size() > 1) {
            Block b = Block.createBlock(values.size(), 0);
            int i = 0;
            for (InternalType v : values) {
                b.set(i, v.toValue());
                i++;
            }
            return Value.createFromBlock(b);
        }
        return values.get(0).toValue();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final PNup other = (PNup) obj;
        if (this.values != other.values
                && (this.values == null
                || !this.values.equals(other.values))) {
            return false;
        }
        if (!Arrays.deepEquals(this.params, other.params)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 41 * hash + (this.values != null ? this.values.hashCode() : 0);
        hash = 41 * hash + Arrays.deepHashCode(this.params);
        return hash;
    }

    @Override
    public String toString() {
        return values.toString();
    }
}